﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Drawing;
using System.Net;
using System.IO;



namespace SmugMugApiWrapper
{

    #region Album Information
    public class SmugMugAlbumInfo
    {
        private int _albumID;
        private string _albumKey;
        private string _albumName;
        private SmugMugCategoryInfo _categoryInfo =null;
        private SmugMugSubCategoryInfo _subCategoryInfo=null;

        public int AlbumID { get { return _albumID; } }
        public string AlbumKey { get { return _albumKey; } }
        public string AlbumName { get { return _albumName; } }
        public SmugMugCategoryInfo Category { get { return _categoryInfo; } }
        public SmugMugSubCategoryInfo SubCategory { get{return _subCategoryInfo;}}

        internal SmugMugAlbumInfo(int albumID, string albumKey, string albumName) {
            _albumName = albumName;
            _albumKey = albumKey;
            _albumID = albumID;
        }
        internal SmugMugAlbumInfo(int albumID, string albumKey, string albumName,SmugMugCategoryInfo category, SmugMugSubCategoryInfo subcategory)
        {
            _albumName = albumName;
            _albumKey = albumKey;
            _albumID = albumID;
            _categoryInfo = category;
            _subCategoryInfo = subcategory;
        }
        internal SmugMugAlbumInfo(int albumID, string albumKey, string albumName, SmugMugCategoryInfo category)
        {
            _albumName = albumName;
            _albumKey = albumKey;
            _albumID = albumID;
            _categoryInfo = category;
         
        }
    }
    #endregion

    #region Category Information
    public class SmugMugCategoryInfo {
        private int _categoryId;
        private string _categoryName;

        public int CategoryID { get { return _categoryId; } }
        public string CategoryName { get { return _categoryName; } }

        internal SmugMugCategoryInfo(int categoryID, string categoryName) {
            _categoryName = categoryName;
            _categoryId = categoryID;
        }
    }
    #endregion

    #region SubCategory Information

    public class SmugMugSubCategoryInfo
    {
        private int _subCategoryId;
        private string _subCategoryName;

        public int SubCategoryID { get { return _subCategoryId; } }
        public string SubCategoryName { get { return _subCategoryName; } }

        internal SmugMugSubCategoryInfo(int subCategoryID, string subCategoryName)
        {
            _subCategoryId= subCategoryID;
            _subCategoryName= subCategoryName;
        }
    }

    #endregion

    #region Image info classes
    public class SmugMugImageInfo
    {
        #region Private variables

        private int _imageID;
        private string _imageKey;

        private string _imageCaption;
        private int _position;
        private DateTime _lastUpdated;
        private int _width;
        private int _height;
        private int _size;
        private int _serial;
        private string _fileName;
        private string _md5Checksum;
        private string _waterMark;
        private bool _hidden;
        private string _format;
        private string _keyWords;
        private DateTime _date;
        private string _albumURL;
        private string _tinyURL;
        private string _mediumURL;
        private string _thumbURL;
        private string _largeURL;
        private string _smallURL;
        private string _xLargeURL;
        private string _x2LargeURL;
        private string _x3LargeURL;
        private string _originalURL;
        private string _albumID;
        private SmugMugImageEXIFData _exifData;

        #endregion
        #region Accessors
        public SmugMugImageEXIFData EXIFData {
            get { return _exifData; }
            set { _exifData = value; }
        }
        public string ImageKey {
            get { return _imageKey; }
        }
        public int ImageID
        {
            get { return _imageID; }
            //set { _imageID = value; }
        }
        public string ImageCaption
        {
            get { return _imageCaption; }
            //set { _imageCaption = value; }
        }
        public int Position
        {
            get { return _position; }
            //set { _position = value; }
        }
        public int Serial
        {
            get { return _serial; }
            //set { _serial = value; }
        }
        public int Size
        {
            get { return _size; }
            //set { _size = value; }
        }
        public int Width
        {
            get { return _width; }
            //set { _width = value; }
        }
        public int Height
        {
            get { return _height; }
            //set { _height = value; }
        }
        public DateTime LastUpdated
        {
            get { return _lastUpdated; }
            //set { _lastUpdated = value; }
        }
        public string FileName
        {
            get { return _fileName; }
            //set { _fileName = value; }
        }
        public string Md5Checksum
        {
            get { return _md5Checksum; }
            //set { _md5Checksum = value; }
        }
        public string WaterMark
        {
            get { return _waterMark; }
            //set { _waterMark = value; }
        }
        public bool Hidden
        {
            get { return _hidden; }
            //set { _hidden = value; }
        }
        public string Format
        {
            get { return _format; }
            //set { _format = value; }
        }
        public string KeyWords
        {
            get { return _keyWords; }
            //set { _keyWords = value; }
        }
        public DateTime Date
        {
            get { return _date; }
            //set { _date = value; }
        }
        public string AlbumURL
        {
            get { return _albumURL; }
            //set { _albumURL = value; }
        }
        public string TinyURL
        {
            get { return _tinyURL; }
            //set { _tinyURL = value; }
        }
        public string ThumbURL
        {
            get { return _thumbURL; }
            //set { _thumbURL = value; }
        }
        public string SmallURL
        {
            get { return _smallURL; }
            //set { _smallURL = value; }
        }
        public string MediumURL
        {
            get { return _mediumURL; }
            //set { _mediumURL = value; }
        }
        public string LargeURL
        {
            get { return _largeURL; }
            //set { _largeURL = value; }
        }
        public string XLargeURL
        {
            get { return _xLargeURL; }
            //set { _xLargeURL = value; }
        }
        public string X2LargeURL
        {
            get { return _x2LargeURL; }
            //set { _x2LargeURL = value; }
        }
        public string X3LargeURL
        {
            get { return _x3LargeURL; }
            //set { _x3LargeURL = value; }
        }
        public string OriginalURL
        {
            get { return _originalURL; }
            //set { _originalURL = value; }
        }
        public string AlbumID
        {
            get { return _albumID; }
            //set { _albumID = value; }
        }
        #endregion
        #region Constructors
        internal SmugMugImageInfo(XmlDocument xml)
        {
            GetMembersFromXML(xml);
        }

        private void GetMembersFromXML(XmlDocument xml)
        {
            XmlAttributeCollection attributes = xml.SelectSingleNode("/rsp/Image").Attributes;

            if (!(attributes.GetNamedItem("FileName") == null))
                _fileName = attributes.GetNamedItem("FileName").InnerText;

            if (!(attributes.GetNamedItem("Caption") == null))
                _imageCaption = attributes.GetNamedItem("Caption").InnerText;

            if (!(attributes.GetNamedItem("id") == null))
                _imageID = Convert.ToInt32(attributes.GetNamedItem("id").InnerText);

            if (!(attributes.GetNamedItem("Key") == null))
                _imageKey = attributes.GetNamedItem("Key").InnerText;

            if (!(attributes.GetNamedItem("Keywords") == null))
                _keyWords = attributes.GetNamedItem("Keywords").InnerText;

            if (!(attributes.GetNamedItem("Position") == null))
                _position = Convert.ToInt32(attributes.GetNamedItem("Position").InnerText);

            if(!(attributes.GetNamedItem("Date") == null))
                DateTime.TryParse(attributes.GetNamedItem("Date").InnerText, out  _date);

            if (!(attributes.GetNamedItem("Format") == null))
                _format = attributes.GetNamedItem("Format").InnerText;

            if (!(attributes.GetNamedItem("Serial") == null))
                _serial = Convert.ToInt32(attributes.GetNamedItem("Serial").InnerText);

            if (!(attributes.GetNamedItem("Watermark") == null))
                _waterMark = attributes.GetNamedItem("Watermark").InnerText;

            if (!(attributes.GetNamedItem("Size") == null))
                _size = Convert.ToInt32(attributes.GetNamedItem("Size").InnerText);

            if (!(attributes.GetNamedItem("Width") == null))
                _width = Convert.ToInt32(attributes.GetNamedItem("Width").InnerText);

            if (!(attributes.GetNamedItem("Height") == null))
                _height = Convert.ToInt32(attributes.GetNamedItem("Height").InnerText);

            if (!(attributes.GetNamedItem("MD5Sum") == null))
                _md5Checksum = attributes.GetNamedItem("MD5Sum").InnerText;

            if (!(attributes.GetNamedItem("Hidden") == null))
                _hidden = attributes.GetNamedItem("Hidden").InnerText == "0" ? false : true;

            if(!(attributes.GetNamedItem("LastUpdated") == null))
                DateTime.TryParse(attributes.GetNamedItem("LastUpdated").InnerText, out _lastUpdated);

            if (!(attributes.GetNamedItem("AlbumURL") == null))
                _albumURL = attributes.GetNamedItem("AlbumURL").InnerText;

            if (!(attributes.GetNamedItem("TinyURL") == null))
                _tinyURL = attributes.GetNamedItem("TinyURL").InnerText;

            if (!(attributes.GetNamedItem("ThumbURL") == null))
                _thumbURL = attributes.GetNamedItem("ThumbURL").InnerText;

            if (!(attributes.GetNamedItem("SmallURL") == null))
                _smallURL = attributes.GetNamedItem("SmallURL").InnerText;

            if (!(attributes.GetNamedItem("MediumURL") == null))
                _mediumURL = attributes.GetNamedItem("MediumURL").InnerText;

            if (!(attributes.GetNamedItem("LargeURL") == null))
                _largeURL = attributes.GetNamedItem("LargeURL").InnerText;

            if (!(attributes.GetNamedItem("XLargeURL") == null))
                _xLargeURL = attributes.GetNamedItem("XLargeURL").InnerText;

            if (!(attributes.GetNamedItem("X2LargeURL") == null))
                _x2LargeURL = attributes.GetNamedItem("X2LargeURL").InnerText;

            if (!(attributes.GetNamedItem("X3LargeURL") == null))
                _x3LargeURL = attributes.GetNamedItem("X3LargeURL").InnerText;

            if (!(attributes.GetNamedItem("OriginalURL") == null))
                _originalURL = attributes.GetNamedItem("OriginalURL").InnerText;

            if (!(attributes.GetNamedItem("Caption") == null))
                _imageCaption = attributes.GetNamedItem("Caption").InnerText;

            
            if(!(xml.SelectSingleNode("/rsp/Image/Album")==null)){
                if (!(xml.SelectSingleNode("/rsp/Image/Album").Attributes.GetNamedItem("id") == null))
                    _albumID = xml.SelectSingleNode("/rsp/Image/Album").Attributes.GetNamedItem("id").InnerText;
            }


        }

        #endregion
    }
    public class SmugMugImagesInfo : IEnumerable
    {
        private SmugMugImageInfo[] _images;

        public SmugMugImageInfo this[int i] {
            get { return _images[i]; }
            set { _images[i] = value; }
        }

        public int Length{
            get { return _images.Length; }
        }
        public SmugMugImagesInfo(SmugMugImageInfo[] imageArray)
        {
            _images = new SmugMugImageInfo[imageArray.Length];
            for (int i = 0; i < imageArray.Length; i++)
            {
                _images[i] = imageArray[i];
            }
        }
        internal SmugMugImagesInfo(List<SmugMugImageInfo> imageList)
        {
            _images = imageList.ToArray();
        }
        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return new SmugMugImageInfoEnum(_images);
        }

        #endregion
    }
    public class SmugMugImageInfoEnum : IEnumerator
    {
        int _position = -1;
        private SmugMugImageInfo[] _images;

        public int Count {
            get { return _images.Length; }
        }
        internal SmugMugImageInfoEnum(SmugMugImageInfo[] list)
        {

            _images = list;
        }
        #region IEnumerator Members

        public object Current
        {
            get
            {
                try
                {
                    return _images[_position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }

            }
        }

        public bool MoveNext()
        {
            _position++;
            return (_position < _images.Length);
        }

        public void Reset()
        {
            _position = -1;
        }

        #endregion
    }
    public class SmugMugImageEXIFData
    {

        #region Private Variables
        /*
         *      * int "ImageID"
                * String "DateTime"
                * String "DateTimeOriginal"
                * String "DateTimeDigitized"
                * String "Make"
                * String "Model"
                * String "ExposureTime"
                * String "Aperture"
                * int "ISO"
                * String "FocalLength"
                * String "FocalLengthIn35mmFilm"
                * String "CCDWidth"
                * String "CompressedBitsPerPixel"
                * int "Flash"
                * int "Metering"
                * int "ExposureProgram"
                * String "ExposureBiasValue"
                * int "ExposureMode"
                * int "LightSource"
                * int "WhiteBalance"
                * String "DigitalZoomRatio"
                * int "Contrast"
                * int "Saturation"
                * int "Sharpness"
                * String "SubjectDistance"
                * String "SubjectDistanceRange"
                * int "SensingMethod"
                * String "ColorSpace"
                * String "Brightness"
         * 
         */

        private bool _hasEXIFData = false;

        private int _ImageID;
        private string _ImageKey;
        private string _DateTime;
        private string _DateTimeOriginal;
        private string _DateTimeDigitized;
        private string _Make;
        private string _Model;
        private string _ExposureTime;
        private string _Aperture;
        private int _ISO;
        private string _FocalLength;
        private string _FocalLengthIn35mmFilm;
        private string _CCDWidth;
        private string _CompressedBitsPerPixel;
        private int _Flash;
        private int _Metering;
        private int _ExposureProgram;
        private string _ExposureBiasValue;
        private int _ExposureMode;
        private int _LightSource;
        private int _WhiteBalance;
        private string _DigitalZoomRatio;
        private int _Contrast;
        private int _Saturation;
        private int _Sharpness;
        private string _SubjectDistance;
        private string _SubjectDistanceRange;
        private int _SensingMethod;
        private string _ColorSpace;
        private string _Brightness;

        #endregion
        #region Accessors

        public bool HasEXIFData {
            get { return _hasEXIFData; }
        }

        public int ImageID
        {
            get { return _ImageID; }
        }

        public string ImageKey
        {
            get { return _ImageKey; }
        }
        public string DateTime
        {
            get { return _DateTime; }
        }
        public string DateTimeOriginal
        {
            get { return _DateTimeOriginal; }
        }
        public string DateTimeDigitized
        {
            get { return _DateTimeDigitized; }
        }
        public string Make
        {
            get { return _Make; }
        }
        public string Model
        {
            get { return _Model; }
        }
        public string ExposureTime
        {
            get { return _ExposureTime; }
        }
        public string Aperture
        {
            get { return _Aperture; }
        }
        public int ISO
        {
            get { return _ISO; }
        }
        public string FocalLength
        {
            get { return _FocalLength; }
        }
        public string FocalLengthIn35mmFilm
        {
            get { return _FocalLengthIn35mmFilm; }
        }
        public string CCDWidth
        {
            get { return _CCDWidth; }
        }
        public string CompressedBitsPerPixel
        {
            get { return _CompressedBitsPerPixel; }
        }
        public int Flash
        {
            get { return _Flash; }
        }
        public int Metering
        {
            get { return _ImageID; }
        }
        public int ExposureProgram
        {
            get { return _ExposureProgram; }
        }
        public string ExposureBiasValue
        {
            get { return _ExposureBiasValue; }
        }
        public int ExposureMode
        {
            get { return _ImageID; }
        }
        public int LightSource
        {
            get { return _LightSource; }
        }
        public int WhiteBalance
        {
            get { return _WhiteBalance; }
        }
        public string DigitalZoomRatio
        {
            get { return _DigitalZoomRatio; }
        }
        public int Contrast
        {
            get { return _Contrast; }
        }
        public int Saturation
        {
            get { return _Saturation; }
        }
        public int Sharpness
        {
            get { return _Sharpness; }
        }
        public string SubjectDistance
        {
            get { return _SubjectDistance; }
        }
        public string SubjectDistanceRange
        {
            get { return _SubjectDistanceRange; }
        }
        public int SensingMethod
        {
            get { return _SensingMethod; }
        }
        public string ColorSpace
        {
            get { return _ColorSpace; }
        }
        public string Brightness
        {
            get { return _Brightness; }
        }
        #endregion
        #region Constructors
        internal SmugMugImageEXIFData(XmlDocument x)
        {
            
            XmlAttributeCollection attributes = x.SelectSingleNode("/rsp/Image").Attributes;
            
            object temp = attributes.GetNamedItem("ID");
            _ImageID =temp ==null?0: Convert.ToInt32(attributes.GetNamedItem("ID").InnerText);


            if (_ImageID > 0)
            {

                if (!(null == attributes.GetNamedItem("Key")))
                    _ImageKey = attributes.GetNamedItem("Key").InnerText;

                if (!(null == attributes.GetNamedItem("DateTime")))
                    _DateTime = attributes.GetNamedItem("DateTime").InnerText;

                if (!(null == attributes.GetNamedItem("DateTimeOriginal")))
                    _DateTimeOriginal = attributes.GetNamedItem("DateTimeOriginal").InnerText;

                if (!(null == attributes.GetNamedItem("_DateTimeDigitized")))
                    _DateTimeDigitized = attributes.GetNamedItem("_DateTimeDigitized").InnerText;

                if (!(null == attributes.GetNamedItem("Make")))
                    _Make = attributes.GetNamedItem("Make").InnerText;

                if (!(null == attributes.GetNamedItem("Model")))
                    _Model = attributes.GetNamedItem("Model").InnerText;

                if (!(null == attributes.GetNamedItem("ExposureTime")))
                    _ExposureTime = attributes.GetNamedItem("ExposureTime").InnerText;

                if (!(null == attributes.GetNamedItem("Aperture")))
                    _Aperture = attributes.GetNamedItem("Aperture").InnerText;

                temp = attributes.GetNamedItem("ISO");
                _ISO = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("ISO").InnerText));

                if (!(null == attributes.GetNamedItem("FocalLength")))
                    _FocalLength = attributes.GetNamedItem("FocalLength").InnerText;

                if (!(null == attributes.GetNamedItem("FocalLengthIn35mmFilm")))
                    _FocalLengthIn35mmFilm = attributes.GetNamedItem("FocalLengthIn35mmFilm").InnerText;

                if (!(null == attributes.GetNamedItem("CCDWidth")))
                    _CCDWidth = attributes.GetNamedItem("CCDWidth").InnerText;

                if (!(null == attributes.GetNamedItem("CompressedBitsPerPixel")))
                    _CompressedBitsPerPixel = attributes.GetNamedItem("CompressedBitsPerPixel").InnerText;

                temp = attributes.GetNamedItem("Flash");
                _Flash = temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("Flash").InnerText);

                temp = attributes.GetNamedItem("Metering");
                _Metering = temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("Metering").InnerText);

                temp = attributes.GetNamedItem("ExposureProgram");
                _ExposureProgram = temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("ExposureProgram").InnerText);

                if (!(null == attributes.GetNamedItem("ExposureBiasValue")))
                    _ExposureBiasValue = attributes.GetNamedItem("ExposureBiasValue").InnerText;

                temp = attributes.GetNamedItem("ExposureMode");
                _ExposureMode = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("ExposureMode").InnerText));

                temp = attributes.GetNamedItem("LightSource").InnerText;
                _LightSource = Convert.ToInt32(temp == null ? 0 : temp);


                temp = attributes.GetNamedItem("WhiteBalance");
                _WhiteBalance = temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("WhiteBalance").InnerText);

                if (!(null == attributes.GetNamedItem("DigitalZoomRatio")))
                    _DigitalZoomRatio = attributes.GetNamedItem("DigitalZoomRatio").InnerText;

                temp = attributes.GetNamedItem("Contrast");
                _Contrast = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("Contrast").InnerText));

                temp = attributes.GetNamedItem("Saturation");
                _Saturation = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("Saturation").InnerText));

                temp = attributes.GetNamedItem("Sharpness");
                _Sharpness = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("Sharpness").InnerText));

                if (!(null == attributes.GetNamedItem("SubjectDistance")))
                    _SubjectDistance = attributes.GetNamedItem("SubjectDistance").InnerText;

                if (!(null == attributes.GetNamedItem("SubjectDistanceRange")))
                    _SubjectDistanceRange = attributes.GetNamedItem("SubjectDistanceRange").InnerText;

                temp = attributes.GetNamedItem("SensingMethod");
                _SensingMethod = (temp == null ? 0 : Convert.ToInt32(attributes.GetNamedItem("SensingMethod").InnerText));

                if (!(null == attributes.GetNamedItem("ColorSpace")))
                    _ColorSpace = attributes.GetNamedItem("ColorSpace").InnerText;

                if (!(null == attributes.GetNamedItem("Brightness")))
                    _Brightness = attributes.GetNamedItem("Brightness").InnerText;
            }


        }
        #endregion

    }
    #endregion

    #region Image classes

    /// <summary>
    /// The bad thing about this class is that it holds an in-memory copy of the image,
    /// which could be bad if you have a large album.  I suggest creating an individual
    /// image instead of grabbing an album's worth, unless you have memory to burn.
    /// </summary>
    public class SmugMugImage : IDisposable
    {

        private System.Drawing.Image _image = null;

        private SmugMugImageInfo _info;
        private bool _lazyImageLoading = true;
        public SmugMugImage(SmugMugImageInfo info, bool lazyImageLoading)
        {

            _info = info;
            _lazyImageLoading = lazyImageLoading;
            if (!_lazyImageLoading)
                LoadImage();
        }
        internal SmugMugImage(SmugMugImageInfo info)
        {
            _info = info;

        }
        private void LoadImage()
        {
            //i wonder what happens when this blows up, or cant find the image, or whathaveyou

            try
            {
                HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(_info.OriginalURL);
                using (WebResponse response = imageRequest.GetResponse())
                {
                    using (Stream recieveStream = response.GetResponseStream())
                    {
                        _image = Image.FromStream(recieveStream);

                    }
                }
            }
            catch
            {
                throw;
            }
        }
        internal SmugMugImage(int smugMugImageID)
        {
            throw new NotImplementedException("Not done yet");
        }
        public SmugMugImageInfo ImageInfo
        {
            get { return _info; }
        }
        public Image Image
        {
            get
            {
                if (_lazyImageLoading && _image == null)
                    LoadImage();
                return _image;

            }
        }
        #region IDisposable Members

        public void Dispose()
        {
            _image.Dispose();
            _image = null;

        }

        #endregion
    }
    public class SmugMugImages : IEnumerable
    {
        private SmugMugImage[] _images;
        public SmugMugImages(SmugMugImage[] imageArray)
        {
            _images = new SmugMugImage[imageArray.Length];
            for (int i = 0; i < imageArray.Length; i++)
            {
                _images[i] = imageArray[i];
            }
        }
        public SmugMugImages(List<SmugMugImage> imageList)
        {
            _images = imageList.ToArray();
        }

        public int Length{
            get { return _images.Length; }
        }
        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return new SmugMugImageEnum(_images);
        }

        #endregion
    }
    public class SmugMugImageEnum : IEnumerator
    {
        int _position = -1;
        private SmugMugImage[] _images;
        public SmugMugImageEnum(SmugMugImage[] list)
        {
            _images = list;
        }
        #region IEnumerator Members

        public object Current
        {
            get
            {
                try
                {
                    return _images[_position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }

            }
        }

        public bool MoveNext()
        {
            _position++;
            return (_position < _images.Length);
        }

        public void Reset()
        {
            _position = -1;
        }

        #endregion
    }
    #endregion
}
